package com.chalet16.fightflood;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class GetLocation implements LocationListener {
	private LocationManager lm;
	private Location location;
	private boolean gpsEnabled, networkEnabled;
	private Context context;
	private static final int TWO_MINUTES = 1000 * 60 * 2;

	public GetLocation(Context gContext) {
		context = gContext;
		lm = (LocationManager) context
				.getSystemService(Context.LOCATION_SERVICE);
	}

	public void start() {
		try {
			lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
					this);
		} catch (Exception ex) {
		}
		try {
			lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
		} catch (Exception ex) {
		}
		try {
			updateLocation(lm
					.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
		} catch (Exception ex) {
		}
		try {
			updateLocation(lm
					.getLastKnownLocation(LocationManager.GPS_PROVIDER));
		} catch (Exception ex) {
		}
		updateStatus();
	}

	public void stop() {
		lm.removeUpdates(this);
	}

	public boolean locate() {
		return location != null;
	}

	private void updateStatus() {
		networkEnabled = gpsEnabled = false;
		try {
			networkEnabled = lm
					.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
		} catch (Exception ex) {
		}
		try {
			gpsEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
		} catch (Exception ex) {
		}
	}

	public void onLocationChanged(Location location) {
		updateLocation(location);
	}

	public void onProviderDisabled(String provider) {
		updateStatus();
	}

	public void onProviderEnabled(String provider) {
		updateStatus();
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	private void updateLocation(Location newLocation) {
		if (newLocation == null) {
			return;
		}
		if (location == null || isBetterLocation(location, newLocation)) {
			location = newLocation;
		}
	}

	public Location getLocation() {
		return location;
	}

	public boolean isNetworkEnabled() {
		return networkEnabled;
	}

	public boolean isGpsEnabled() {
		return gpsEnabled;
	}

	/**
	 * Determines whether one Location reading is better than the current
	 * Location fix
	 * 
	 * From: http://developer.android.com/guide/topics/location/obtaining-user-
	 * location.html Under Apache 2.0 license
	 * 
	 * @param location
	 *            The new Location that you want to evaluate
	 * @param currentBestLocation
	 *            The current Location fix, to which you want to compare the new
	 *            one
	 */
	protected boolean isBetterLocation(Location oldLocation,
			Location currentBestLocation) {
		if (currentBestLocation == null) {
			// A new location is always better than no location
			return true;
		}

		// Check whether the new location fix is newer or older
		long timeDelta = oldLocation.getTime() - currentBestLocation.getTime();
		boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
		boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
		boolean isNewer = timeDelta > 0;

		// If it's been more than two minutes since the current location, use
		// the new location
		// because the user has likely moved
		if (isSignificantlyNewer) {
			return true;
			// If the new location is more than two minutes older, it must be
			// worse
		} else if (isSignificantlyOlder) {
			return false;
		}

		// Check whether the new location fix is more or less accurate
		int accuracyDelta = (int) (oldLocation.getAccuracy() - currentBestLocation
				.getAccuracy());
		boolean isLessAccurate = accuracyDelta > 0;
		boolean isMoreAccurate = accuracyDelta < 0;
		boolean isSignificantlyLessAccurate = accuracyDelta > 200;

		// Check if the old and new location are from the same provider
		boolean isFromSameProvider = isSameProvider(oldLocation.getProvider(),
				currentBestLocation.getProvider());

		// Determine location quality using a combination of timeliness and
		// accuracy
		if (isMoreAccurate) {
			return true;
		} else if (isNewer && !isLessAccurate) {
			return true;
		} else if (isNewer && !isSignificantlyLessAccurate
				&& isFromSameProvider) {
			return true;
		}
		return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
			return provider2 == null;
		}
		return provider1.equals(provider2);
	}
}
